""" Authentication & authz support """

from datetime import datetime

from sqlobject import SQLObject, SQLObjectNotFound, RelatedJoin, DatabaseIndex
from sqlobject.col import UnicodeCol, StringCol, DateTimeCol, IntCol, ForeignKey
from mnemoply.model.model_object import ModelObject
from turbogears import identity
import cherrypy
from mnemoply.model.hub import __connection__
from mnemoply._renewed_utils import buildChunksOr
from mnemoply._renewed_utils import find_class
class Visit(SQLObject):
    class sqlmeta:
        table = "visit"

    visit_key = StringCol(length=40, alternateID=True, alternateMethodName="by_visit_key")
    created = DateTimeCol(default=datetime.now)
    expiry = DateTimeCol()

    def lookup_visit(cls, visit_key):
        try:
            return cls.by_visit_key(visit_key)
        except SQLObjectNotFound:
            return None
    lookup_visit = classmethod(lookup_visit)

class VisitIdentity(SQLObject):
    visit_key = StringCol(length=40, alternateID=True, alternateMethodName="by_visit_key")
    user_id = IntCol()

class AuthGroup(SQLObject):
    group_name = StringCol(length=16, alternateID=True, alternateMethodName="by_group_name")
    display_name = UnicodeCol(length=255)
    created = DateTimeCol(default=datetime.now)

    # collection of all users belonging to this group
    users = RelatedJoin("AuthUser", intermediateTable="auth_user_group",
        joinColumn="group_id", otherColumn="user_id")

    # collection of all permissions for this group
    permissions = RelatedJoin("AuthPermission", joinColumn="group_id",
                              intermediateTable="auth_group_permission",
                              otherColumn="permission_id")

    title = property(lambda self: self.group_name)

class AuthUser(ModelObject):
    model_title = 'AuthUser'
    class sqlmeta:
        table = "prod_v2.auth_user"

    user_name = UnicodeCol(length=40, alternateID=True,
                           alternateMethodName="by_user_name", title=_("Login"))
    display_name = UnicodeCol(length=255, default='', title=_("Display name"))
    password = UnicodeCol(length=40, title=_("Password"))
    created = DateTimeCol(default=datetime.now)
    office = ForeignKey("Office", default=None,  title=_("Office"))
    person = ForeignKey("Personality", default=None,  title=_("Person"))
    # groups this user belongs to
    groups = RelatedJoin("AuthGroup", intermediateTable="auth_user_group",
                         joinColumn="user_id", otherColumn="group_id")
    
    
    name_for_session = property(lambda(self):'user_%s_%s'%(self.user_name, self.id))
    filters_dict_where = property(lambda(self): cherrypy.session.get(self.name_for_session)
                                  if cherrypy.session.get(self.name_for_session)
                                  else self.set_filter_to_session())

    def set_filter_to_session(self, ):
        result = dict(office=False, Faculty = False)
        result['office'] = self.build_filter('Office')
        result['faculty'] = self.build_filter('Faculty')
        cherrypy.session[self.name_for_session] = result
        return result
        
    
    
    def build_filter(self,model_name):
        model = find_class('AuthUser'+model_name.capitalize())
        select = list(model.selectBy(user=self))
        column_name = model_name.lower()
        print select
        lst = [getattr(row, column_name) for row in select]
        if (None in lst):
            return ' True '
        if not lst:
            return ' False '
        lst = [" %s_id = %s " %(column_name, flt.id) for flt in lst  ]
        query = " OR ".join(lst)
        return '(%s)'%query    
    
    
    def get_filter_where_by_controller(self, controller):
        lst = [ self.filters_dict_where.get( flt) for flt in controller.filter_by_user]
        return ' AND '.join(lst)
        
    
                
        
    def _get_name_groups(self):
        return [g.group_name for g in self.groups]

    def _get_permissions(self):
        perms = set()
        for g in self.groups:
            perms = perms | set(g.permissions)
        return perms

    permissions = property(_get_permissions)

    def _set_password(self, cleartext_password):
        """Runs cleartext_password through the hash algorithm before saving."""
        hash = identity.encrypt_password(cleartext_password)
        self._SO_set_password(hash)

    def set_password_raw(self, password):
        """Saves the password as-is to the database."""
        self._SO_set_password(password)

    title = property(lambda self: self.user_name)
    
class AuthPermission(SQLObject):
    permission_name = StringCol(length=60, alternateID=True,
                                 alternateMethodName="by_permission_name")
    description = UnicodeCol(length=255, default='')

    groups = RelatedJoin("AuthGroup",
                        intermediateTable="auth_group_permission",
                        joinColumn="permission_id",
                        otherColumn="group_id")

    title = property(lambda self: self.permission_name)


class Menu(ModelObject):
    """
        Certificate type. Need for English groups.
    """

    model_title = _("Menu")

    name = UnicodeCol(length=31, notNull=True, title=_("Name"))    
    href = StringCol(length=63, notNull=False, title=_("href"))
    ordinal = IntCol(notNull=True, default=0, title=_("Ordinal"))
    parent = ForeignKey('Menu', default=0, title=_("Parent"))

    menuOrdinalUnique = DatabaseIndex('parent', 'ordinal', unique=True)
    title = property(lambda self: self.name if not self.name is None else '')
    need_recreate = True
    
    @classmethod
    def replace_menu(cls):
        cls.need_recreate = False
    @classmethod
    def is_need_recreate(cls):
        return cls.need_recreate
    
    def _get_name_groups(self):
        return [g.group_name for g in self.groups]
    
    def has_permission(self,user):
        user_groups = set(user._get_name_groups())
        menu_groups = set(self._get_name_groups())
        return  ('dba' in user_groups ) or (menu_groups & user_groups)

    @classmethod
    def handle_update(cls, obj, kw):
        cls.need_recreate = True

    @classmethod
    def handle_delete(cls, obj, post_funcs):
        cls.need_recreate = True
    @classmethod
    def handle_create(cls, kw, post_funcs):
        cls.need_recreate = True



class AuthUserOffice(ModelObject):
    model_title = 'AuthUserOffice'
    user = ForeignKey('AuthUser', notNull=True, title=_("User"))
    office = ForeignKey('Office', notNull=True, title=_("Office"))
    title = ""
    class sqlmeta:
        table = "prod_v2.auth_user_office"

class AuthUserFaculty(ModelObject):
    model_title = 'AuthUserFaculty'
    user = ForeignKey('AuthUser', notNull=True, title=_("User"))
    faculty = ForeignKey('Faculty', notNull=True, title=_("Faculty"))
    title = ""
    class sqlmeta:
        table = "prod_v2.auth_user_faculty"

class AuthUserOrg(ModelObject):
    model_title = 'AuthUserOrg'
    user = ForeignKey('AuthUser', notNull=True, title=_("User"))
    organization = ForeignKey('Organization', notNull=True, title=_("Organization"))
    title = ""
    class sqlmeta:
        table = "prod_v2.auth_user_org"
